﻿using System;
using System.Buffers;
using System.IO;
using System.Threading;
using System.Xml.Linq;

using iTool.Cloud.DataSearch.ServiceProvider;
using iTool.Common;

using Lucene.Net.Store;

using Orleans;

namespace iTool.Cloud.DataSearch.DirectoryProvider
{
    /// <summary>
    /// 读取数据
    /// </summary>
    public class iToolCloudIndexInput : BufferedIndexInputX
    {
        readonly IClusterClient iCluster;
        IIndexFieldManageService iIndexInputService;
        //readonly ILuceneDirectoryService iLuceneDirectoryService;
        readonly string fieldName;
        readonly long tableNameHash;
        private long _position;
        private readonly bool isLocalService;
        public iToolCloudIndexInput(long tableNameHash, string fieldName, IOContext context, bool isLocalService) : base(fieldName, context)
        {
            this.isLocalService = isLocalService;
            this.tableNameHash = tableNameHash;
            this.fieldName = fieldName;
            this.iCluster = iBox.GetService<IClusterClient>("IClusterService");
            this.iIndexInputService =
                this.isLocalService ? IDirectoryServiceFactory<IndexFieldManageService>.GetService(tableNameHash, fieldName) :
                this.iCluster.GetGrain<IIndexFieldManageService>(tableNameHash, fieldName);
        }


        public override long Length
        {
            get
            {
                try
                {
                    var service = this.iIndexInputService.LengthAsync();
                    return service.Result;
                }
                catch (Exception)
                {
                    Thread.Sleep(10);
                    this.iIndexInputService =
                        this.isLocalService ? IDirectoryServiceFactory<IndexFieldManageService>.GetService(tableNameHash, fieldName) :
                        this.iCluster.GetGrain<IIndexFieldManageService>(this.tableNameHash, fieldName);
                    return this.Length;
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            if(this.isLocalService) IDirectoryServiceFactory<IndexFieldManageService>.Dispose(tableNameHash, fieldName);
            //this.iIndexInputService.DisposeAsync().Wait();
        }

        /// <summary>
        /// 实现缓冲区再填充。从输入中的当前位置读取字节。
        /// </summary>
        /// <param name="b">要读取字节的数组</param>
        /// <param name="offset">数组中开始存储字节的偏移量</param>
        /// <param name="length">要读取的字节数</param>
        /// <exception cref="NotImplementedException"></exception>
        protected override void ReadInternal(byte[] b, int offset, int length)
        {
            try
            {
                //Console.WriteLine($"ReadInternal:{offset},{length}");
                var buffResult = this.iIndexInputService.ReadInternalAsync(_position, offset, length).Result;
                buffResult.CopyTo(b, offset);
                if (this.isLocalService)
                {
                    ArrayPool<byte>.Shared.Return(buffResult);
                }
                //var stream = new MemoryStream(buffResult);
                //stream.Read(b, offset, length);
                _position += length;
            }
            catch (Exception)
            {
                Thread.Sleep(100);
                this.iIndexInputService =
                    this.isLocalService ? IDirectoryServiceFactory<IndexFieldManageService>.GetService(tableNameHash, fieldName) :
                    this.iCluster.GetGrain<IIndexFieldManageService>(this.tableNameHash, fieldName);
                throw;
            }
        }

        /// <summary>
        /// 执行搜索。设置此文件中的当前位置，下一个 ReadInternal 将出现在该位置
        /// </summary>
        /// <param name="pos"></param>
        protected override void SeekInternal(long pos)
        {
            _position = pos;
        }

    }
}
